﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace SpeedTest
{
	public partial class AttachmentsForm : Form
	{
		Data data = null;
		private string uploadPath = String.Empty;
		string itemID = String.Empty;

		public AttachmentsForm(Data data, string itemID)
		{
			InitializeComponent();
			this.data = data;
			this.itemID = itemID;
		}

		private void AttachmentsForm_Load(object sender, EventArgs e)
		{
			if (!GetAttachmentOptions())
			{
				MessageBox.Show("An error occurred while retrieving the attachment options.");
				EnableInput(false);
			}
			else
			{
				LoadAttachments();
			}
		}

		private void EnableInput(bool enable)
		{
			btnAdd.Enabled = enable;
			btnDelete.Enabled = enable;
			lstAttachments.Enabled = enable;
		}

		private bool LoadAttachments()
		{
			if (data != null)
			{
				DataTable table = data.GetAttachmentsByCaseID(itemID);
				//add the current items
				if (table != null)
				{
					for (int i = 0; i < table.Rows.Count; i++)
					{
						string fileName = table.Rows[i]["FileName"].ToString();
						ListViewItem lvi = lstAttachments.Items.Add(Path.GetFileName(fileName), GetMimeImageIndex(Path.GetExtension(fileName)));
						lvi.Tag = table.Rows[i]["ID"].ToString();
					}
				}
			}

			return false;
		}

		private bool GetAttachmentOptions()
		{
			if (data != null)
			{
				DataTable table = data.GetServerSettings();
				if (table.Rows.Count > 0)
				{
					uploadPath = table.Rows[0]["Path"].ToString();

					return true;
				}
			}

			return false;
		}

		private void lstAttachments_DragEnter(object sender, DragEventArgs e)
		{
			if (e.Data.GetDataPresent(DataFormats.FileDrop) || e.Data.GetDataPresent(DataFormats.Text)) { e.Effect = DragDropEffects.Copy; }
		}

		private void lstAttachments_DragDrop(object sender, DragEventArgs e)
		{
			if(e.Data.GetDataPresent(DataFormats.FileDrop))
			{
				string[] filePaths = (string[])e.Data.GetData(DataFormats.FileDrop, false); //possibly set to true

				foreach (string file in filePaths)
				{
					AddAttachment(file);
				}
			}
			else if(e.Data.GetDataPresent(DataFormats.Text))
			{
				try
				{
					string file = Path.GetFileNameWithoutExtension(Path.GetTempFileName()) + ".txt";
					string filePath = Path.Combine(Application.StartupPath, "temp");
					if (!Directory.Exists(filePath))
					{
						Directory.CreateDirectory(filePath);
					}
					file = Path.Combine(filePath, file);
					StreamWriter writer = File.CreateText(file);
					writer.Write((string)e.Data.GetData(DataFormats.Text));
					writer.Close();
					AddAttachment(file);
					File.Delete(file);
				}
				catch(Exception ex)
				{
					MessageBox.Show("Unable to create the file due to the following error" + System.Environment.NewLine + ex.Message);
				}
			}
		}

		private void AddAttachment(string file)
		{
			this.Cursor = Cursors.WaitCursor;

			string shortFileName = Path.GetFileName(file);
			if (File.Exists(file))
			{
				long index = AttachmentExists(shortFileName);
				if (index != -1)
				{
					DialogResult res = MessageBox.Show("The file " + shortFileName + " already exists. Do you want to update the file?", "File Exists", MessageBoxButtons.YesNo);
					if (res == DialogResult.Yes)
					{
						UpdateAttachment(shortFileName, index);
						UploadFile(file, true);
					}
				}
				else
				{
					long id = InsertAttachment(shortFileName);
					if (!UploadFile(file, false))
					{
						DeleteAttachment(id.ToString(), shortFileName, false);
					}
					else 
					{
						ListViewItem lvi = lstAttachments.Items.Add(Path.GetFileName(file), GetMimeImageIndex(Path.GetExtension(file)));
						lvi.Tag = id.ToString();
					}
				}
			}

			this.Cursor = Cursors.Default;
		}

		private long AttachmentExists(string fileName)
		{
			string fullPath = Path.Combine(uploadPath, itemID);

			if (File.Exists(Path.Combine(fullPath, fileName)))
			{
				if (data != null)
				{
					return data.GetAttachmentIDByName(itemID, fileName);
				}
			}
			return -1;
		}

		private long InsertAttachment(string fileName)
		{
			if (data != null)
			{
				DataTable table = new DataTable();
				table.Columns.Add("CaseID");
				table.Columns.Add("FileName");
				table.Columns.Add("UploadedBy");

				string[] row = new string[3];
				row[0] = itemID;
				row[1] = fileName;
				row[2] = data.User.UserID;

				table.Rows.Add(row);

				return data.InsertAttachment(table);
			}

			return -1;
		}

		private bool UpdateAttachment(string fileName, long index)
		{
            if (data != null)
            {
                DataTable table = new DataTable();
                table.Columns.Add("FileName");
                table.Columns.Add("DateUpdated");
                table.Columns.Add("UpdatedBy");

                string[] row = new string[3];
                row[0] = fileName;
                row[1] = DateTime.Now.ToString("MM/dd/yyyy");
                row[2] = data.User.UserID;
                table.Rows.Add(row);

                data.UpdateAttachmentByID(table, index.ToString());
            }
			return false;
		}

		private bool DeleteAttachment(string id, string fileName, bool deleteFromServer)
		{
			this.Cursor = Cursors.WaitCursor;

			if (data != null)
			{
				data.DeleteAttachmentByID(id);

				if (deleteFromServer)
				{
					string fullPath = Path.Combine(uploadPath, itemID);
					try
					{
						File.Delete(Path.Combine(fullPath, fileName));
					}
					catch(Exception e)
					{
						MessageBox.Show("Unable to delete the file due to the following error" + System.Environment.NewLine + e.Message);
					}
				}
			}

			this.Cursor = Cursors.Default;

			return true;
		}

		private bool UploadFile(string fileName, bool overwrite)
		{
			if (Directory.Exists(uploadPath))
			{
				try
				{//see if the item id directory exists
					string fullPath = Path.Combine(uploadPath, itemID);
					
					if (!Directory.Exists(fullPath))
					{
						Directory.CreateDirectory(fullPath);
					}
					
					string destFileName = Path.Combine(fullPath, Path.GetFileName(fileName));
					File.Copy(fileName, destFileName, overwrite);

					return true;
				}
				catch (Exception e)
				{
					MessageBox.Show("Unable to copy the file due to the following error" + System.Environment.NewLine + e.Message);
				}
			}
			else
			{
				MessageBox.Show("The directory specified in the server settings does not exist. Please contact your administrator");
			}

			return false;
		}

        /*
        application/		application-x-executable.png		0
        audio/			audio-x-generic.png			1
        image/			image-x-generic.png			2
        application/x-zip-compressed		package-x-generic.png	3
        text/			text-x-generic.png			4
        video/			video-x-generic.png			5
        application/msword			x-office-document.png	6
        application/vnd.ms-excel		x-office-spreadsheet.png	7

         *///Path.GetExtension(fileName).ToLower();
        private int GetMimeImageIndex(string extension)
        {
            string contentType = "application/unknown";

            Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(extension);
            if (regKey != null && regKey.GetValue("Content Type") != null)
            {
                contentType = regKey.GetValue("Content Type").ToString();
            }

            string[] baseType = contentType.Split('/');

            if (baseType.Length > 0)
            {
                switch (baseType[0])
                {
                    case "application":
                        {
                            if (contentType.Equals("application/x-zip-compressed")) { return 3; }
                            if (contentType.Equals("application/msword")) { return 6; }
                            if (contentType.Equals("application/vnd.ms-excel")) { return 7; }
                            return 0;
                        }
                    case "audio":
                        return 1;
                    case "image":
                        return 2;
                    case "text":
                        return 4;
                    case "video":
                        return 5;
                    default:
                        break;
                }
            }

            return 4;   //default index.
        }

		private void btnAdd_Click(object sender, EventArgs e)
		{
			OpenFileDialog ofd = new OpenFileDialog();
			DialogResult res = ofd.ShowDialog();

			if (res != DialogResult.Cancel)
			{
				foreach (string file in ofd.FileNames)
				{
					AddAttachment(file);
				}
			}
		}

		private void btnDelete_Click(object sender, EventArgs e)
		{
			if (lstAttachments.SelectedItems.Count > 0)
			{
				PromptAndDelete();
			}
		}

		private void PromptAndDelete()
		{
			DialogResult res = MessageBox.Show("Are you sure you wish to delete the selected attachments?", "Confirm Deletion", MessageBoxButtons.YesNo);
			if (res == DialogResult.Yes)
			{
				foreach (ListViewItem lvi in lstAttachments.SelectedItems)
				{
					string id = (string)lvi.Tag;
					if (!String.IsNullOrEmpty(id))
					{
						DeleteAttachment(id, lvi.Text, true);
					}

					lstAttachments.Items.Remove(lvi);
				}
			}
		}

		private void lstAttachments_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Delete && lstAttachments.SelectedItems.Count > 0)
			{
				PromptAndDelete();
			}
		}

		private void lstAttachments_MouseDoubleClick(object sender, MouseEventArgs e)
		{
			ListViewHitTestInfo hit = lstAttachments.HitTest(e.Location);

			if (hit.Item != null)
			{
				if (Directory.Exists(uploadPath))
				{
					try
					{//see if the item id directory exists
						string fullPath = Path.Combine(uploadPath, itemID);
						string itemFileName = Path.Combine(fullPath, Path.GetFileName(hit.Item.Text));

						AttachmentOpenSave openSave = new AttachmentOpenSave();
						openSave.ShowDialog();

						switch (openSave.Result)
						{
							case OpenSaveResult.Open:
								Process.Start(itemFileName);
								break;
							case OpenSaveResult.Save:
								SaveFileDialog sfd = new SaveFileDialog();
								sfd.OverwritePrompt = true;
								sfd.CheckPathExists = true;

								DialogResult res = sfd.ShowDialog();
								if (res != DialogResult.Cancel)
								{
									File.Copy(itemFileName, sfd.FileName);
								}
								break;
							case OpenSaveResult.Cancel:
								break;
						}
						
					}
					catch (Exception ex)
					{
						MessageBox.Show("Unable to open the file due to the following error" + System.Environment.NewLine + ex.Message);
					}
				}
				else
				{
					MessageBox.Show("The directory specified in the server settings does not exist. Please contact your administrator");
				}
			}
		}

        private void lstAttachments_AfterLabelEdit(object sender, LabelEditEventArgs e)
        {
			if (String.IsNullOrEmpty(e.Label)) { return; }

            ListViewItem lvi = lstAttachments.Items[e.Item];
            if (lvi != null)
            {
                try
                {
                    string dirPath = Path.Combine(uploadPath, itemID);
                    string destFilePath = Path.Combine(dirPath, e.Label);
                    string sourceFilePath = Path.Combine(dirPath, data.GetAttachmentNameByID(lvi.Tag.ToString()));
                    File.Copy(sourceFilePath, destFilePath);
                    File.Delete(sourceFilePath);

                    UpdateAttachment(e.Label, Int64.Parse(lvi.Tag.ToString()));
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void lstAttachments_MouseClick(object sender, MouseEventArgs e)
        {

        }
	}
}
